using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace odata_linq
{
    internal class ODataProvider : QueryProvider
    {
        private readonly string _url;

        public ODataProvider(string url)
        {
            _url = url;
        }

        public IQueryable<T> CreateQuery<T>(string collection)
        {
            return new Query<T>(this, collection);
        }

        public override TResult Execute<TResult>(Expression expression)
        {
            var collectionName = expression.GetCollectionName();

            var reuqestUrl = _url + '/' + collectionName;

            reuqestUrl += Translate(expression);

            var response = UrlHelper.Get(reuqestUrl);

            return DeserializeObject<TResult>(response);
        }

        private T DeserializeObject<T>(string json)
        {
            try
            {
                return JsonConvert.DeserializeObject<T>(json);
            }
            catch (JsonSerializationException ex)
            {

            }

            var jobject = JsonConvert.DeserializeObject(json) as JObject;

            var items =  JsonConvert.DeserializeObject<T>(jobject["d"].ToString());

            return items;
        }

        private string Translate(Expression expression)
        {
            var visitor = new ODataExpressionVisitor();

            return visitor.Parse(expression);
        }
    }
}